package ca.swank.hardquor;
import java.util.TreeSet;

/**
* Provides logic for maintaining the state of a hardquor game in progress.
* The hardquorBoard class can be used for move validation (is a move legal)
* and board state tracking.
*
* @author Jesse Wilson
* @version 1.0 10/18/2001
*/
public interface hardquorBoard
{

  public static int PLAYER_ONE = 0;
  public static int PLAYER_TWO = 1;
  public static int PLAYER_NONE = 7;

  public static int DIR_ABOVE = 2;
  public static int DIR_RIGHT = 3;
  public static int DIR_BELOW = 4;
  public static int DIR_LEFT = 5;

  public static int DIR_CRISSCROSS = 6;

  /**
  * returns the integer corresponding to the game's winner. If no winner
  * has been found, the value of PLAYER_NONE will be returned. This can
  * used to check if a game is complete; a game is complete only when a
  * winner has been decided.
  *
  * @return one of PLAYER_ONE, PLAYER_TWO or PLAYER_NONE who one the game
  */
  public int getWinner();

  /**
  * returns the integer corresponding to which player is responsible for
  * the next move. PLAYER_ONE is the first player to make a move. When the
  * game is complete, this value is undefined.
  *
  * @return either PLAYER_ONE or PLAYER_TWO if the game is incomplete
  */
  public int getTurn();

  /**
  * gets the number of walls remaining for the player as specified by
  * the argument playerNumber. Each time a player places a wall on the
  * board, this value is decremented for that player. When the player
  * has 0 walls remaining, it is no longer legal for the player to place
  * walls.
  *
  * @param playerNumber the player to look up walls remaining for
  * @return a number between 0 and the initial number of walls for
  *        this player, inclusive.
  */
  public int getPlayerWalls(int playerNumber);

  /**
  * returns a player number corresponding to the occupant of the
  * specified square.
  *
  * @param square a 2 cell integer array representing the coordinate
  *        in question. square[0] is the X value, square[1] is the y value.
  *        The behaviour is undefined for malformed or out of range coordinates.
  * @return one of PLAYER_ONE, PLAYER_TWO or PLAYER_NONE who occupies square
  */
  public int getSquareOccupant(int[] square);

  /**
  * returns an integer array representing the coordinate location of the
  * specified player.
  *
  * @param player either PLAYER_ONE or PLAYER_TWO.
  * @return a 2 cell integer array representing the coordinate location
  *        of the player.
  */
  public int[] getPlayerLocation(int player);

  /**
  * returns an 2 dimensional integer array containing all of the finish
  * locations for the specified player. Use the first dimension to choose
  * a finish square, and the second dimension to choose X or Y. That is,
  * values are returned in the form return[finish#][x|y].
  *
  * @param player either PLAYER_ONE or PLAYER_TWO.
  * @return a 2 dimension array containing all finish locations for player
  */
  public int[][] getPlayerFinish(int player);

  /**
  * tests if moves can be made from the specified square in the specified
  * direction. This will return false if there exists a wall from this square
  * in the direction specified, or if that direction from this square is off
  * of the board. Using DIR_CRISSCROSS for the direction parameter can be
  * used to test if a wall can be placed with this cell as it's bottom-left
  * coordinate.
  *
  * @param square a 2 cell integer array representing the coordinate
  *        in question. square[0] is the X value, square[1] is the y value.
  *        The behaviour is undefined for malformed or out of range coordinates.
  * @param direction one of DIR_ABOVE, DIR_BELOW, DIR_LEFT, DIR_RIGHT or
  *        DIR_CRISSCROSS.
  * @return true iff there is a path from square in that direction or when
  *        DIR_CRISSCROSS is used, true if a wall can be placed with square at
  *        it's bottom left corner.
  */
  public boolean isAdjacent(int[] square, int direction);

  /**
  * checks all legal moves from the specified origin. This method takes into
  * account jumping and non-adjacent squares.
  * <STRONG>Note:</STRONG> legal moves from this position to not take into
  * account the state of the game, such as which player has the turn, or
  * whether the game is over. Do not use this method for move validation.
  *
  * @param origin a 2 cell integer array representing the source coordinate.
  * @return a TreeSet containing all of the 2 cell integer coordinate arrays
  *        that are valid moves from origin.
  */
  public TreeSet getLegalMoves(int[] origin);

  /**
  * checks to see if a move from source to target is a legal move. This takes
  * into account the location of source, the location of target, cell adjacencies,
  * jumps, turns, game over and other game logic.
  *
  * @param source a 2 cell integer array representing the source coordinate.
  *        This should always equal the location of the player who has turn.
  * @param target a 2 cell integer array representing the target coordinate.
  *        This should always equal an element in the set of getLegalMoves(source)
  * @return an integer value corresponding to one of the hardquorUserGame error codes.
  *        The error code hardquorUserGame.ERROR_NONE will be returned for legal moves.
  */
  public int isLegalMove(int[] source, int[] target);

  /**
  * checks to see if placing a wall specified is a legal move. This takes
  * into account blocking players from their finish, cell adjacencies,
  * turns, game over and other game logic. Note that this does not check which
  * player is attempting this move, which should be managed by an external source.
  *
  * @param a1 a 2 cell integer array representing one cell on the A side of the
  *        wall. This cell should be adjacent to b1 and beside a2.
  * @param a2 a 2 cell integer array representing other cell on the A side of the
  *        wall. This cell should be adjacent to b2 and beside a1.
  * @param b1 a 2 cell integer array representing one cell on the B side of the
  *        wall. This cell should be adjacent to a1 and beside b2.
  * @param b2 a 2 cell integer array representing one cell on the B side of the
  *        wall. This cell should be adjacent to a2 and beside b1.
  * @return an integer value corresponding to one of the hardquorUserGame error codes.
  *        The error code hardquorUserGame.ERROR_NONE will be returned for legal moves.
  */
  public int isLegalMove(int[] a1, int[] a2, int[] b1, int[] b2);

  /**
  * moves a player on the board. Error checking is not guaranteed, so users should
  * call isLegalMove(source, target) with the return value hardquorUserGame.ERROR_NONE
  * before making this move. Otherwise the game's state may be broken. The move
  * shifts the player's location, player occupancy and sets the turn to the next
  * player in sequence.
  *
  * @param source a 2 cell integer array representing the source coordinate.
  *        This should always equal the location of the player who has turn.
  * @param target a 2 cell integer array representing the target coordinate.
  *        This should always equal an element in the set of getLegalMoves(source)
  * @return an integer value corresponding to one of the hardquorUserGame error codes.
  *        The error code hardquorUserGame.ERROR_NONE will be returned for legal moves.
  */
  public void makeMove(int[] source, int[] target);

  /**
  * places the wall on the board. Error checking is not guaranteed, so users should
  * call isLegalMove(a1, a2, b1, b2) with the return value hardquorUserGame.ERROR_NONE
  * before making this move. Otherwise the game's state may be broken.
  * The move adjusts cell adjacencies, decrements a wall from the current turned player,
  * and sets the turn to the next player in sequence.
  *
  * @param a1 a 2 cell integer array representing one cell on the A side of the
  *        wall. This cell should be adjacent to b1 and beside a2.
  * @param a2 a 2 cell integer array representing other cell on the A side of the
  *        wall. This cell should be adjacent to b2 and beside a1.
  * @param b1 a 2 cell integer array representing one cell on the B side of the
  *        wall. This cell should be adjacent to a1 and beside b2.
  * @param b2 a 2 cell integer array representing one cell on the B side of the
  *        wall. This cell should be adjacent to a2 and beside b1.
  * @return an integer value corresponding to one of the hardquorUserGame error codes.
  *        The error code hardquorUserGame.ERROR_NONE will be returned for legal moves.
  */
  public void makeMove(int[] a1, int[] a2, int[] b1, int[] b2);

  /**
  * computes a 2 dimensional interpretation of the current board. Each square in
  * the array stores an integer corresponding how many squares away from the nearest
  * origin cell it is. This tracks distance around walls on the board, so placing
  * a wall between a cell and the nearest origin cell should cause that's cell's
  * value to be raised. This can be useful for determining player scores or writing
  * AI logic. If a square is not reachable from the origin cells, then that square
  * inherits the value Integer.MAX_VALUE.
  * <STRONG>Note:</STRONG> this method returns a traditional integer array. It does
  * not return coordinate cells.
  *
  * @param origin 2 dimensional integer array containing all of the origin
  *        cells to compute distances from. Use the first dimension to choose
  *        an origin square, and the second dimension to choose X or Y. That is,
  *        values are passed in the form origin[cell#][x|y]
  * @return a 2 dimensional integer array mapping the distance of square return[x][y]
  *        to the nearest origin square.
  */
  public int[][] getDistanceBoard(int[][] origin);
  

  /**
   * creates a 2 dimensional map such that map[x][y] equals the shortest distance
   * to the specified player's finish. If map[x][y] is a cell on the player's finish,
   * then the value will be 0. 
   *
   * although this is equivilent to getDistanceBoard(getPlayerFinish(player)), use
   * this method as it may be optimized.
   *
   * @param player the player's finish to use
   * 
   * @return a 2 dimensional integer array mapping the distance of square return[x][y]
   *        to the nearest finish for player.
   */
  public int[][] getDistanceHomeBoard(int player);

  /**
  * computes the width (x-domain) of the board.
  *
  * return the number of squares across the x axis on the board
  */
  public int getWidth();

  /**
  * computes the height (y-range) of the board.
  *
  * return the number of squares across the y axis on the board
  */
  public int getHeight();

}